Better handling around #if conditionals - #227
Conversation
JonatanWaern
commented
Jun 9, 2026
- Refactor how we store object conds for objectdecls
- Add logic to select between hashif branches
88ae3a0 to
0c8cd42
Compare
Signed-off-by: Jonatan Waern <jonatan.waern@intel.com>
0c8cd42 to
b7a331b
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
This PR improves handling of #if/#else conditionals during analysis by introducing expression evaluation support and using existence conditions to avoid reporting conflicts across mutually exclusive branches.
Changes:
- Added an
evaluationmodule to evaluate a small subset of expressions for conditional existence checks. - Refactored
ExistConditionstorage to useArcand added helpers (exists,guaranteed_exists,guaranteed_excluded_from) to reason about conditional branches. - Updated object/spec symbol collection and conflict detection to consider evaluated
#ifconditions and avoid conflicts between#ifand corresponding#else.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| src/analysis/templating/objects.rs | Uses ExistCondition evaluation to filter specs/decls and refines conflict reporting to ignore provably exclusive branches |
| src/analysis/templating/mod.rs | Exposes the new evaluation module |
| src/analysis/templating/evaluation.rs | Introduces expression evaluation utilities used for #if condition resolution |
| src/analysis/structure/toplevel.rs | Stores conditional stacks in Arc and adds existence/exclusion helpers on ExistCondition |
| CHANGELOG.md | Documents improved conflict handling across #if/#else and built-in version-condition behavior |
Suppressed comments (1)
src/analysis/structure/toplevel.rs:97
is_samecan returntruefor different-length conditional stacks becausezip()truncates to the shorter iterator (e.g.,[A]vs[A,B]will returntrue). Add an explicit length equality check before the loop (or compare the full vectors) so only identical conditional stacks are treated as the same.
(ExistCondition::Conditional(selfvec),
ExistCondition::Conditional(othervec)) => {
// Currently we cannt check if a condition is equivalent with another,
// so we will only check if they are literally the same condition expression
for ((_, cond1),
(_, cond2)) in selfvec.iter().zip(othervec.iter()) {
if cond1 != cond2 {
return false;
}
}
true
},
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| // same nested hashifs | ||
| // As it turns out, collision is guaranted regardless of | ||
| // which branch they are in | ||
| // Currently we cannt check if a condition is equivalent with another, |
b7a331b to
21f1f59
Compare
There was a problem hiding this comment.
🟡 Changes recommended
It contains a correctness issue in ExistCondition::guaranteed_overlaps plus several documentation/formatting problems in CHANGELOG that should be fixed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 4
- Review effort level: Lite
21f1f59 to
877999e
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new expression evaluation contains confirmed logic defects that can cause #if conditions to be treated incorrectly, undermining the PR’s core behavioral goal.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
src/analysis/structure/toplevel.rs:90
ExistCondition::guaranteed_overlapsuseszip()without checking thatselfvecandothervechave the same length. That can returntruewhen one condition list is a strict prefix of the other (e.g., nested#ifs), incorrectly treating conditions as guaranteed-overlapping and leading to missed/incorrect conflict filtering.
(ExistCondition::Conditional(selfvec),
ExistCondition::Conditional(othervec)) => {
// TODO/NOTE: Currently we cannt check if a condition is equivalent with another,
// so we will only check if they are literally the same condition expression
for ((invert1, cond1),
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
Rather speculative for now, as exact future info required to make this choice isn't well-known Signed-off-by: Jonatan Waern <jonatan.waern@intel.com>
I don't wanna go _too_ far back with this, but fixed some obviously-visible errors Signed-off-by: Jonatan Waern <jonatan.waern@intel.com>
877999e to
d275d19
Compare
There was a problem hiding this comment.
🟡 Changes recommended
It introduces a correctness issue in ExistCondition::guaranteed_overlaps (prefix-length conditions can be misclassified as guaranteed overlapping), which should be fixed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
CHANGELOG.md:12
- These changelog entries have awkward grammar ("properly not report", "branches on conditions"); tightening the wording will make the release notes clearer.
- The DLS will now properly not report conflicts between statements in a `#if` and its corresponding `#else` branch
- The DLS will now consider all `#if` branches on conditions directly based on `dml_1_2` and `dml_1_4` dead or alive appropriately
- Files reviewed: 5/5 changed files
- Comments generated: 4
- Review effort level: Lite
| // TODO/NOTE: Currently we cannt check if a condition is equivalent with another, | ||
| // so we will only check if they are literally the same condition expression | ||
| for ((invert1, cond1), | ||
| (invert2, cond2)) in selfvec.iter().zip(othervec.iter()) { | ||
| if cond1 != cond2 || invert1 != invert2 { |
| // Currently we cannt check if a condition is equivalent with another, | ||
| // so we will only check if they are literally the same condition expression |
| // NOTE: 'used' here marks if this type of declaration is the one used for the name | ||
| // of this symbol. Which declaration is used in inferred by the ranking and existconditions | ||
| // of the declarations |
| let mut constants: Vec<Constant> = vec![]; | ||
| let mut constants: Vec<ObjectDecl<Constant>> = vec![]; | ||
|
|
||
| // In order to not overly complicate the types, |